<?php
/**
 * Created by PhpStorm.
 * User: apple
 * Date: 17/2/27
 * Time: 上午10:25
 */
require_once(dirname(__FILE__) . '/UPush/UPush.php');

class PushMsg{
    protected $push_model = null;
    protected $production_mode = true;

    // 友盟 key
    public $u_config = array(
        'ios' => array(
            array(
                'app_key' => '5f06b307978eea082dbda301',
                'app_master_secret' => '4dsr0p8pbcglxy5w00zkkqcvatde9wve'
            ),
        ),
        'android' => array(
            array(
                'app_key' => '58f03797717c196a1f000d43',
                'app_master_secret' => '0tlrqo59hak9iglbokqyn6ihcftv3rml'
            )
        )
    );
    public function __construct(){}



    #约会推送
    function addPushOfDate($nickname, $push_token){
        $type = 4;// 1 公共消息    2 ios   3 Android   4 指定用户
        $note = "您的好友".$nickname."邀请您加入约会，您可以在“我关心的人”中的“位置约定”查看。";
        $title = "约会邀请";
        $push_msg = array(
            'type' => $type,
            'title' => $title,
            'alert' => array('title' => $title, 'body' => $note, 'subtitle' => ''),
            'text' => $note,
            'description' => mb_substr( $title, 0, 15, 'utf-8').'...',
            'production_mode' => $this->production_mode //正式/测试环境
        );
        $extra = array(  //扩展字段
            'type' => '3',////1-文字推送，跳首页；2-邀请好友推送，点击跳转到好友消息页，3-好友约会页
        );
        $this->pushMsg($type, $push_msg, array($push_token), $extra);
    }

    #邀请好友推送
    function addPushOfInvite($nickname, $push_token){
        $type = 4;// 1 公共消息    2 ios   3 Android   4 指定用户
        $note = '用户' . $nickname . '请求添加您为好友';
        $title = "好友邀请";
        $push_msg = array(
            'type' => $type,
            'title' => '',
            'alert' => array('title' => $title, 'body' => $note, 'subtitle' => ''),
            'text' => $note,
            'description' => mb_substr($title, 0, 15, 'utf-8').'...',
            'production_mode' => $this->production_mode //正式/测试环境
        );
        $extra = array(  //扩展字段
            'type' => '2',////1-文字推送，跳首页；2-邀请好友推送，点击跳转到好友消息页，3-好友约会页
        );
        $this->pushMsg($type, $push_msg, array($push_token), $extra);
    }





    /**********************************************************************************************************************/
    /**
     * 推送类型
     * @param int $type 推送类型  1 公共消息    2 ios   3 Android   4 指定用户
     * @param array $msg_body 消息主体 [
     *                                  'ticker' => '通知栏提示文字', Android 选填 不填为 title
     *                                  'title' => '标题', Android 必选
     *                                  'text' => '消息', Android 必选
     *                                  'alert' => '消息', ios 可选 ios消息提示文字 不填为 text
     *                                  'after_open' => '安卓打开后操作', 选填 默认 go_app
     *                                  ... 其他这段可参考文档
     *                                ]
     * @param array $uids 要推送用户id [1232, 12343] type为4不能为空
     * @param array $extra 可选 用户自定义key-value [key => value, ...]
     * @return void
     */
    public function pushMsg($type, $msg_body, $device_token = '', $extra = array()){
        if( $type == 1 ){
            $ret = $this->publicPushMsg($msg_body, $extra);
        }elseif( $type == 2 ){
            $ret = $this->iosPublicMsg($msg_body, $extra);
        }elseif( $type == 3 ){
            $ret = $this->androidPublicMsg($msg_body, $extra);
        }elseif( $type == 4){
            $ret = $this->privatePushMsg($msg_body, $device_token, $extra);
        }
        return $ret;
    }

    // 推送公共消息
    public function publicPushMsg($msg_body, $extra){
        $is_succ = true;
        $error_msg = '';
        $data = array();
        $adr = $this->androidPublicMsg($msg_body, $extra);
        $ios = $this->iosPublicMsg($msg_body, $extra);
        if( $adr[0] === false ){
            $is_succ = false;
            $error_msg .= "android_err：{$adr[1]}；";
        }
        $data['android'] = $adr[2];
        if( $ios[0] === false ){
            $is_succ = false;
            $error_msg .= "ios_err：{$ios[1]}；";
        }
        $data['ios'] = $ios[2];
        return array($is_succ, $error_msg, $data);
    }

    // 推送安卓公共消息
    private function androidPublicMsg($msg_body, $extra){
        $android_config = $this->u_config['android'];
        $ret = array();
        foreach($android_config as $key => $value){
            $ret[$key] = (new UPush($value['app_key'], $value['app_master_secret']))->sendAndroidBroadcast($this->initAndroidBody($msg_body), $extra);
        }
        return $ret;
    }

    //推送 ios公共消息
    private function iosPublicMsg($msg_body, $extra){
        $ios_config = $this->u_config['ios'];
        $ret = array();
        foreach($ios_config as $key => $value){
            $ret[$key] = (new UPush($value['app_key'], $value['app_master_secret']))->sendIOSBroadcast($this->initIosBody($msg_body), $extra);
        }
        return $ret;
    }

    // 推送 指定用户消息
    private function privatePushMsg($msg_body, $device_token, $extra){
        if( empty($device_token) ) return array(false, '请选择要发送的用户！', array());
        $is_succ = true;
        $error_msg = '';
        $ret = array();

        #只有ios采用友盟单推
        $tokens['ios'] = array($device_token);
        if( !empty($tokens['android']) && is_array($tokens['android']) ){
            $ret['android'] = $this->androidPrivateMsg($msg_body, $tokens['android'], $extra);
        }
        if( !empty($tokens['ios']) && is_array($tokens['ios']) ){
            $ret['ios'] = $this->iosPrivateMsg($msg_body, $tokens['ios'], $extra);
        }
        return $ret;
    }

    // 安卓私有消息推送
    protected function androidPrivateMsg($msg_body, $token_arr, $extra){
        $android_config = $this->u_config['android'];
        $ret = array();
        foreach($token_arr as $key => $tokens){
            $config = $android_config[$key];
            if( count($tokens) < 500 )
                $ret[$key] = $this->androidListcastMsg($config, $msg_body, implode(',', $tokens), $extra);
            else
                $ret[$key] = $this->androidFilecastMsg($config, $msg_body, implode(',', $tokens), $extra);
        }
        return $ret;
    }

    // 安卓 列表消息 小于500条
    protected function androidListcastMsg($config, $msg_body, $token_str, $extra){
        $push_model = new UPush($config['app_key'], $config['app_master_secret']);
        return $push_model->sendAndroidListcast($this->initAndroidBody($msg_body), $token_str, $extra);
    }

    // 安卓 文件消息 大于500条
    protected function androidFilecastMsg($config, $msg_body, $token_str, $extra){
        $push_model = new UPush($config['app_key'], $config['app_master_secret']);
        return $push_model->sendAndroidFilecast($this->initAndroidBody($msg_body), $token_str, $extra);
    }

    // 苹果 私有消息推送
    protected function iosPrivateMsg($msg_body, $token_arr, $extra){
        $ios_config = $this->u_config['ios'];
        $ret = array();
        foreach($token_arr as $key => $tokens){
            $config = $ios_config[$key];
            if( count($tokens) < 500 )
                $ret[$key] = $this->iosListcastMsg($config, $msg_body, implode(',', $tokens), $extra);
            else
                $ret[$key] = $this->iosFilecastMsg($config, $msg_body, implode(',', $tokens), $extra);
        }
        return $ret;
    }

    // ios 列表消息 小于500条
    protected function iosListcastMsg($config, $msg_body, $token_str, $extra){
        $push_model = new UPush($config['app_key'], $config['app_master_secret']);
        return $push_model->sendIOSListcast($this->initIosBody($msg_body), $token_str, $extra);
    }

    // ios 文件消息 大于500条
    protected function iosFilecastMsg($config, $msg_body, $token_str, $extra){
        $push_model = new UPush($config['app_key'], $config['app_master_secret']);
        return $push_model->sendIOSFilecast($this->initIosBody($msg_body), $token_str, $extra);
    }

    // 通过用户uid获取用户推送tokens
    protected function uidsToTokens($uids){
        $user_model = new UserModel();
        $users = $user_model->getInfoByUids($uids);
        $tokens = array('android' => array(), 'ios' => array());
        foreach($users as $user){
            if( $user['device_type'] == 2 ){
                $tokens['ios'][] = $user['device_token'];
            }elseif( $user['device_type'] == 3 ){
                $tokens['android'][] = $user['device_token'];
            }
        }
        return $tokens;
    }

    // 公共的key
    protected $public_key = array(
        "device_tokens", // 可选 设备唯一表示 多个device_token以英文逗号间隔
        "alias", //  可选 当type=customizedcast时, 开发者填写自己的alias
        "alias_type", // 可选 当type=customizedcast时，必填，alias的类型,
        "file_id", // 可选 当type=filecast时，file内容为多条device_token,
        "filter", // 可选 终端用户筛选条件,如用户标签、地域、应用版本以及渠道等
        "production_mode", // 可选 正式/测试模式 "true/false"
        "description", // 可选 发送消息描述，建议填写
        "thirdparty_id", // 可选 开发者自定义消息标识ID
        "start_time", // 可选 定时发送时间 "YYYY-MM-DD HH:mm:ss"
        "expire_time", // 可选 消息过期时间,其值不可小于发送时间 "YYYY-MM-DD HH:mm:ss"
        "max_send_num" // 可选 发送限速，每秒发送的最大条数
    );

    // ios 私有的key
    protected $ios_key = array(
        "alert", // 必填 消息
        "badge",
        "sound",
        "content-available",
    );

    // Android 私有的key
    protected $android_key = array(
        "display_type", // 必填 消息类型，值可以为 以默认 notification
        "ticker", // 必填 通知栏提示文字 默认等于 title
        "title", // 必填 通知标题
        "text", // 必填 通知文字描述
        "after_open", // 必填 值可以为: "go_app": 打开应用 "go_url": 跳转到URL "go_activity": 打开特定的activity "go_custom": 用户自定义内容。
        "builder_id", "icon", "largeIcon", "img", "play_vibrate", "play_lights",
        "play_sound", "url", "activity", "custom");

    // 初始化 Android 的提交数据
    protected function initAndroidBody($msg_body){
        $data = array();
        foreach(array_merge($this->public_key, $this->android_key) as $value){
            if( array_key_exists($value, $msg_body) ){
                $data[$value] = $msg_body[$value];
            }
        }
        if( empty($data['ticker']) ) $data['ticker'] = $msg_body['title'];
        if( empty($data['after_open']) ) $data['after_open'] = 'go_app';
        return $data;
    }

    // 初始化 ios 的提交数据
    protected function initIosBody($msg_body){
        $data = array();
        foreach(array_merge($this->public_key, $this->ios_key) as $value){
            if( array_key_exists($value, $msg_body) ){
                $data[$value] = $msg_body[$value];
            }
        }
        if( empty($data['alert']) ) $data['alert'] = $msg_body['alert'];
        return $data;
    }

    // 友盟错误码
    static public $error_codes = array(
        1000 => "请求参数没有appkey",
        1001 => "请求参数没有payload",
        1002 => "请求参数payload中没有body",
        1003 => "display_type为message时，请求参数没有custom",
        1004 => "请求参数没有display_type",
        1005 => "img url格式不对，请以https或者http开始",
        1006 => "sound url格式不对，请以https或者http开始",
        1007 => "url格式不对，请以https或者http开始",
        1008 => "display_type为notification时，body中ticker不能为空",
        1009 => "display_type为notification时，body中title不能为空",
        1010 => "display_type为notification时，body中text不能为空",
        1011 => "play_vibrate的值只能为true或者false",
        1012 => "play_lights的值只能为true或者false",
        1013 => "play_sound的值只能为true或者false",
        1014 => "task-id没有找到",
        1015 => "请求参数中没有device_tokens",
        1016 => "请求参数没有type",
        1017 => "production_mode只能为true或者false",
        1018 => "appkey错误：指定的appkey尚未开通推送服务",
        1019 => "display_type填写错误",
        1020 => "应用组中尚未添加应用",
        2000 => "该应用已被禁用",
        2001 => "过期时间必须大于当前时间",
        2002 => "定时发送时间必须大于当前时间",
        2003 => "过期时间必须大于定时发送时间",
        2004 => "IP白名单尚未添加, 请到网站后台添加您的服务器IP白名单。",
        2005 => "该消息不存在",
        2006 => "validation token错误",
        2007 => "未对请求进行签名",
        2008 => "json解析错误",
        2009 => "请填写alias或者file_id",
        2010 => "与alias对应的device_tokens为空",
        2011 => "alias个数已超过50",
        2012 => "此appkey今天的广播数已超过3次",
        2013 => "消息还在排队，请稍候再查询",
        2014 => "消息取消失败，请稍候再试",
        2015 => "device_tokens个数已超过50",
        2016 => "请填写filter",
        2017 => "添加tag失败",
        2018 => "请填写file_id",
        2019 => "与此file_id对应的文件不存在",
        2020 => "服务正在升级中，请稍候再试",
        2021 => "appkey不存在",
        2022 => "payload长度过长",
        2023 => "文件上传失败，请重试",
        2024 => "限速值必须为正整数",
        2025 => "aps字段不能为空",
        2026 => "1分钟内发送任务次数超出3次",
        2027 => "签名不正确",
        2028 => "时间戳已过期",
        2029 => "content内容不能为空",
        2030 => "launch_from/not_launch_from条件中的日期须小于发送日期",
        2031 => "filter格式不正确",
        2032 => "未上传生产证书，请到Web后台上传",
        2033 => "未上传开发证书，请到Web后台上传",
        2034 => "证书已过期",
        2035 => "定时任务证书过期",
        2036 => "时间戳格式错误",
        2038 => "文件上传失败",
        2039 => "时间格式必须是yyyy-MM-dd HH:mm:ss",
        2040 => "过期时间不能超过7天",
        2046 => "定时推送时间不能超过创建推送时间+7天",
        3000 => "数据库错误",
        3001 => "数据库错误",
        3002 => "数据库错误",
        3003 => "数据库错误",
        3004 => "数据库错误",
        4000 => "系统错误",
        4001 => "系统忙",
        4002 => "操作失败",
        4003 => "appkey格式错误",
        4004 => "消息类型格式错误",
        4005 => "msg格式错误",
        4006 => "body格式错误",
        4007 => "deliverPolicy格式错误",
        4008 => "失效时间格式错误",
        4009 => "单个服务器队列已满",
        4010 => "设备号格式错误",
        4011 => "消息扩展字段无效",
        4012 => "没有权限访问",
        4013 => "异步发送消息失败",
        4014 => "appkey和device_tokens不对应",
        4015 => "没有找到应用信息",
        4016 => "文件编码有误",
        4017 => "文件类型有误",
        4018 => "文件远程地址有误",
        4019 => "文件描述信息有误",
        4020 => "device_token有误(注意，友盟的device_token是严格的44位字符串)",
        4021 => "HSF异步服务超时",
        4022 => "appkey已经注册",
        4023 => "服务器网络异常",
        4024 => "非法访问",
        4025 => "device-token全部失败",
        4026 => "device-token部分失败",
        4027 => "拉取文件失败",
        5000 => "device_token错误",
        5001 => "证书不存在",
        5002 => "p,d是umeng保留字段",
        5003 => "alert字段不能为空",
        5004 => "alert只能是String类型",
        5005 => "device_token格式错误",
        5006 => "创建socket错误",
        5007 => "certificate_revoked错误",
        5008 => "certificate_unkown错误",
        5009 => "handshake_failure错误",
    );

}